package ace.module.product.core.impl.manager.impl;

import ace.cmp.core.constants.CoreConstant;
import ace.cmp.data.spring.data.jdbc.querydsl.rsql.core.model.SaveContext;
import ace.cmp.data.spring.data.jdbc.querydsl.rsql.core.utils.SaveContextUtils;
import ace.cmp.util.AceAssertUtils;
import ace.module.common.core.impl.manager.impl.AbstractEntityOfAppManager;
import ace.module.product.api.model.dto.PmsProductSkuDto;
import ace.module.product.api.model.input.PmsProductSkuSaveInput;
import ace.module.product.core.impl.dao.entity.PmsProduct;
import ace.module.product.core.impl.dao.entity.PmsProductAttribute;
import ace.module.product.core.impl.dao.entity.PmsProductAttributeValue;
import ace.module.product.core.impl.dao.entity.PmsProductSku;
import ace.module.product.core.impl.dao.model.bo.PmsProductAttributeAndValueSaveBo;
import ace.module.product.core.impl.dao.model.bo.PmsProductAttributeSaveBo;
import ace.module.product.core.impl.dao.repository.PmsProductSkuRepository;
import ace.module.product.core.impl.manager.PmsProductSkuManager;
import ace.module.product.core.impl.manager.helper.PmsProductAttributeHelperMgr;
import ace.module.product.core.impl.manager.helper.PmsProductAttributeValueHelperMgr;
import java.util.Objects;
import java.util.Optional;
import java.util.TreeMap;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

/**
 * 商品Sku基础资料 spring data jdbc querydsl rsql manager implement.
 *
 * @author Caspar
 */
@Slf4j
@AllArgsConstructor
@Component
public class PmsProductSkuManagerImpl
    extends AbstractEntityOfAppManager<PmsProductSku, Long, PmsProductSkuDto>
    implements PmsProductSkuManager {

  private final PmsProductAttributeHelperMgr pmsProductAttributeHelperMgr;
  private final PmsProductAttributeValueHelperMgr pmsProductAttributeValueHelperMgr;
  private final PmsProductSkuRepository pmsProductSkuRepository;

  @Override
  public SaveContext<PmsProductSku> assembleSaveContext(
      SaveContext<PmsProduct> pmsProductSaveContext,
      PmsProductAttributeSaveBo pmsProductAttributeSaveBo,
      PmsProductSkuSaveInput pmsProductSkuSaveInput
  ) {

    this.checkSkuInAttributeAndValues(pmsProductAttributeSaveBo, pmsProductSkuSaveInput.getAttributes());
    PmsProduct pmsProduct = pmsProductSaveContext.getData();
    PmsProductSku pmsProductSku = null;
    String attributeKey = this.buildAttributeKey(pmsProductSkuSaveInput.getAttributes());
    if (pmsProductSaveContext.isModify()) {
      pmsProductSku = this.pmsProductSkuRepository.findByPmsAppIdAndProductIdAndAttributeKeyAndDeleteFlag(
          pmsProduct.getPmsAppId(),
          pmsProduct.getId(),
          attributeKey,
          CoreConstant.DELETE_FLAG_NOT
      );
    }
    boolean isAdd = Objects.isNull(pmsProductSku);
    if (isAdd) {
      pmsProductSku = PmsProductSku.builder()
          .id(this.getNewId())
          .pmsAppId(pmsProduct.getPmsAppId())
          .productId(pmsProduct.getId())
          .shopId(pmsProduct.getShopId())
          .attributeKey(attributeKey)
          .build();
    }
    BeanUtils.copyProperties(pmsProductSkuSaveInput, pmsProductSku);

    return SaveContextUtils.of(pmsProductSku, isAdd);
  }

  @Override
  public String buildAttributeKey(TreeMap<String, String> map) {
    return map.entrySet()
        .stream()
        .map(entry -> entry.getKey() + entry.getValue())
        .collect(Collectors.joining(""));
  }

  @Override
  public void checkValidSkuTotalCount(PmsProductAttributeSaveBo pmsProductAttributeSaveBo, int pmsProductSkuCount) {
    int validSkuTotalCount = 0;

    for (int i = 0; i < pmsProductAttributeSaveBo.getAttributeAndValues().size(); i++) {
      PmsProductAttributeAndValueSaveBo pmsProductAttributeAndValueSaveBo = pmsProductAttributeSaveBo.getAttributeAndValues().get(i);
      int valueSize = pmsProductAttributeAndValueSaveBo.getAttributeValues().getOriginData().size();
      if (validSkuTotalCount == 0) {
        validSkuTotalCount = valueSize;
      } else {
        validSkuTotalCount = validSkuTotalCount * valueSize;
      }
    }

    AceAssertUtils.isFalse(validSkuTotalCount == pmsProductSkuCount, "无法保存sku,sku数量不正确 %s/%s", pmsProductSkuCount, validSkuTotalCount);
  }

  private void checkSkuInAttributeAndValues(PmsProductAttributeSaveBo pmsProductAttributeSaveBo, TreeMap<String, String> attributes) {

    attributes.entrySet()
        .forEach(entry -> {
          String attributeName = entry.getKey();
          Optional<PmsProductAttribute> pmsProductAttributeOptional = pmsProductAttributeHelperMgr.findByName(
              pmsProductAttributeSaveBo.getAttributes().getNewOrModifyOriginData(),
              attributeName
          );
          AceAssertUtils.isTrue(pmsProductAttributeOptional.isEmpty(), "无法保存sku,[%s]商品属性缺失", attributeName);

          String attributeValue = entry.getValue();
          Optional<PmsProductAttributeValue> pmsProductAttributeValueOptional = pmsProductAttributeValueHelperMgr.findByValue(
              pmsProductAttributeSaveBo.getAttributeValues().getNewOrModifyOriginData(),
              attributeValue
          );
          AceAssertUtils.isTrue(pmsProductAttributeValueOptional.isEmpty(), "无法保存sku,[%s]商品属性值缺失", attributeValue);
        });
  }
}
